/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.seguradora.model.repository.impl;

import br.com.seguradora.exception.PersistenciaException;
import br.com.seguradora.model.Associado;
import br.com.seguradora.model.Modelo;
import br.com.seguradora.model.Plano;
import br.com.seguradora.model.Veiculo;
import br.com.seguradora.model.constant.StatusPlano;
import br.com.seguradora.model.constant.TipoVeiculo;
import br.com.seguradora.model.repository.TodosPlanos;
import br.com.seguradora.persistence.GerenciadorDeConexao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @author Diego
 */
public class TodosPlanosImpl implements TodosPlanos {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Plano plano) throws PersistenciaException {
        if (plano == null) {
            throw new PersistenciaException("Não foi informado o plano a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO PLANO(ID, DATA_ENTRADA, DATA_VENCIMENTO, STATUS, ID_VEICULO) VALUES(NULL, ?, ?, ?, ?);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setDate(1, new java.sql.Date(plano.getDataEntrada().getTime()));
            pr.setDate(2, new java.sql.Date(plano.getDataVencimento().getTime()));
            pr.setString(3, plano.getStatus().name());
            pr.setLong(4, plano.getVeiculo().getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                plano.setId(id);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar o plano.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Override
    public boolean atualizar(Plano plano) throws PersistenciaException {
        if (plano == null) {
            throw new PersistenciaException("Não foi informado o plano a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE PLANO SET STATUS=? WHERE ID=?;");
            pr.setString(1, plano.getStatus().name());
            pr.setLong(2, plano.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar o plano.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Plano> listarTodos(int... limits) throws PersistenciaException {
        List<Plano> lista = new ArrayList<Plano>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT P.ID, P.DATA_ENTRADA, P.DATA_VENCIMENTO, P.STATUS, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM PLANO P INNER JOIN VEICULO V ON P.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID ORDER BY P.ID DESC LIMIT ?,?;");
            pr.setInt(1, limits[0]);
            pr.setInt(2, limits[1]);
            rs = pr.executeQuery();
            while (rs.next()) {
                Plano plano = this.criarPlano(rs);
                lista.add(plano);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os planos recentes.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Plano> listarPelaPlaca(String placa) throws PersistenciaException {
        List<Plano> lista = new ArrayList<Plano>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT P.ID, P.DATA_ENTRADA, P.DATA_VENCIMENTO, P.STATUS, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM PLANO P INNER JOIN VEICULO V ON P.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID WHERE V.PLACA=? ORDER BY V.PLACA;");
            pr.setString(1, placa);
            rs = pr.executeQuery();
            while (rs.next()) {
                Plano plano = this.criarPlano(rs);
                lista.add(plano);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os planos pela placa.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }
    
    private Plano criarPlano(ResultSet rs) throws PersistenciaException {
        Plano plano = null;
        try {
            plano = new Plano(rs.getLong("ID"));
            plano.setDataEntrada(new Date(rs.getDate("DATA_ENTRADA").getTime()));
            plano.setDataVencimento(new Date(rs.getDate("DATA_VENCIMENTO").getTime()));
            plano.setStatus(StatusPlano.valueOf(rs.getString("STATUS")));
            Veiculo veiculo = new Veiculo(rs.getLong("ID_VEICULO"));
            veiculo.setCorPredominante(rs.getString("COR_PREDOMINANTE"));
            veiculo.setModelo(new Modelo(rs.getString("MODELO")));
            veiculo.setTipo(TipoVeiculo.valueOf(rs.getString("TIPO")));
            veiculo.setPlaca(rs.getString("PLACA"));
            veiculo.setAssociado(new Associado(rs.getLong("ID_ASSOCIADO"), rs.getString("NOME_ASSOCIADO")));
            plano.setVeiculo(veiculo);
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do plano.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return plano;
    }

    @Override
    public List<Plano> listarPeloAssociado(String associado) throws PersistenciaException {
        List<Plano> lista = new ArrayList<Plano>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT P.ID, P.DATA_ENTRADA, P.DATA_VENCIMENTO, P.STATUS, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM PLANO P INNER JOIN VEICULO V ON P.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID WHERE A.NOME LIKE ? ORDER BY A.NOME;");
            pr.setString(1, "%" + associado + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Plano plano = this.criarPlano(rs);
                lista.add(plano);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os planos pelo associado.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public boolean hasPlano(Veiculo veiculo) throws PersistenciaException {
        boolean possui = false;
        
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT P.ID FROM PLANO P INNER JOIN VEICULO V ON V.ID = P.ID_VEICULO WHERE P.ID_VEICULO=? AND P.STATUS='EM_VIGOR' LIMIT 0,1;");
            pr.setLong(1, veiculo.getId());
            rs = pr.executeQuery();
            if (rs.first()) {
                long id = rs.getLong("ID");
                if(id > 0) {
                    possui = true;
                }
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível verificar se determinado veículo tem plano.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        
        return possui;
    }
}
